//引入登录、退出、获取用户信息的api接口函数
import {
  login,
  logout,
  getInfo
} from '@/api/user'
//引入获取token、保存token、删除token的函数
import {
  getToken,
  setToken,
  removeToken
} from '@/utils/auth'
//引入重置路由的函数
import {
  resetRouter
} from '@/router'

//引入路由器对象
import router from '@/router'

// 引入常量路由，动态路由，任意路由
import {
  constantRoutes,
  asyncRoutes,
  anyRoutes
} from '@/router/routes'

import cloneDeep from 'lodash/cloneDeep'

//初始化state对象的回调函数
const getDefaultState = () => {
  return {
    token: getToken(),
    name: '', //用户名字
    avatar: '', //用户头像
    buttons: [], // 按钮权限相关的数组
    roles: [], // 角色权限相关的数组
    asyncRoutes: [], // 异步路由数组
    routes: [] // 所有路由的相关数组

  }
}

//创建一个state对象
const state = getDefaultState()

const mutations = {
  //重置state对象
  RESET_STATE: (state) => {
    Object.assign(state, getDefaultState())
  },
  //保存token
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  //保存用户名字
  SET_NAME: (state, name) => {
    state.name = name
  },
  //保存用户头像
  SET_AVATAR: (state, avatar) => {
    state.avatar = avatar
  },

  // 保存用户信息
  SET_USER(state, {
    avatar,
    name,
    buttons,
    roles
  }) {
    state.avatar = avatar // 头像
    state.name = name // 用户名字
    state.buttons = buttons // 按钮数组
    state.roles = roles // 权限的数组
  },

  // 保存路由信息
  SET_ROUTES(state, asyncRoutes) {
    // 一定是合并后的(已经过滤后的动态路由的数组)
    // 存储动态路由数组数据
    state.asyncRoutes = asyncRoutes
    // 合并路由数组
    state.routes = constantRoutes.concat(asyncRoutes, anyRoutes)
    // 再把异步路由和任意路由重新加入到常量路由中,真正的在路由器中合并路由数据
    router.addRoutes([...asyncRoutes, anyRoutes])
  }
}

const actions = {
  // 登录
  login({
    commit
  }, userInfo) {
    //结构账号和密码
    const {
      username,
      password
    } = userInfo
    return new Promise((resolve, reject) => {
      //调用login的api接口函数，并传入账号和密码
      login({
        username: username.trim(),
        password: password
      }).then(response => {
        //登录成功后结构出所需要的data数据
        const {
          data
        } = response
        //token要保存
        commit('SET_TOKEN', data.token)
        //使用cookie方式存储token
        setToken(data.token)
        resolve()
      }).catch(error => {
        //如果登录失败
        reject(error)
      })
    })
  },

  // 获取用户信息
  getInfo({
    commit,
    state
  }) {
    return new Promise((resolve, reject) => {
      //获取用户信息，不用传入token，因为已经在请求头加入了token
      getInfo().then(response => {
        //结构出data数据
        const {
          data
        } = response
        if (!data) {
          //如果没有用户信息，则提示重新进行登录
          return reject('请重新登录！！！')
        }
        // 保存用户信息
        commit('SET_USER', data);
        // 加工路由对象
        const resultRoutes = filterAsyncRoutes(cloneDeep(asyncRoutes), data.routes);
        // 保存路由信息
        commit('SET_ROUTES', resultRoutes);
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  },

  // 退出
  logout({
    commit,
    state
  }) {
    return new Promise((resolve, reject) => {
      logout(state.token).then(() => {
        removeToken() // 删除token
        resetRouter() //重置路由
        commit('RESET_STATE') //重置state
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // 移除token
  resetToken({
    commit
  }) {
    return new Promise(resolve => {
      removeToken() // 移除token
      commit('RESET_STATE') //重置state
      resolve()
    })
  }
}

// 过滤路由对象信息数据的函数
function filterAsyncRoutes(routes, routeNames) {
  return routes.filter(route => {
    // 判断父级路由是否存在
    if (routeNames.includes(route.name)) {
      // 判断子级路由是否存在
      if (route.child && route.child.length > 0) {
        // 过滤子级路由
        const childRoute = filterAsyncRoutes(route.child, routeNames);
        // 判断是否有内容
        if (childRoute && childRoute.length > 0) {
          route.child = childRoute; // 把子级路由重新赋给父级路由
          return true;
        }
        return false;
      }
      return true;
    }
    return false;
  })
}

export default {
  namespaced: true, //开启命名空间
  state,
  mutations,
  actions
}
